# -*- coding: utf-8 -*-

from common import orm
from common.mch import handler as mch_handler
from common.recharge import db as recharge_db
from common.timer import TIMER_EVENT_TYPE, TimerEvent, EventHandler
from common.utils import track_logging
from common.utils import tz
from common.withdraw import db as withdraw_db

_LOGGER = track_logging.getLogger(__name__)


def _calc_delay_notify_ts(order):
    """
    采用退避重发机制 15/15/30/180/1800/1800/1800/1800/3600/3600/...
    最长24小时
    """
    payed_ts = tz.to_ts(order.updated_at)
    if tz.now_ts() - payed_ts > 24 * 3600:
        _LOGGER.warn('pay[%s] notify has expired in 24 hours!', order.id)
        return None
    if order.notify_count > 100:
        _LOGGER.warn('pay[%s] notify has expired > 100 notify_count!', order.id)
        return None
    if order.notify_count <= 2:
        return 15
    if order.notify_count == 3:
        return 30
    if order.notify_count == 4:
        return 180
    if order.notify_count <= 8:
        return 1800
    return 3600


def submit_notify_event(order, event_type):
    event_msg = {'order_id': order.id}
    delay_ts = _calc_delay_notify_ts(order)
    if not delay_ts:
        return
    expire_ts = tz.now_ts() + delay_ts
    event_id = TimerEvent.submit(
        event_type, event_msg, expire_ts)
    _LOGGER.info(
        'start timer to notify event in %s seconds later. event id[%s]', delay_ts, event_id)


class MchNotifyHandler(EventHandler):

    def process(self, event_msg):
        _LOGGER.info('mch notify Event [%s]' % event_msg)
        order_id = event_msg['order_id']
        try:
            # notify
            _LOGGER.info('to process notify_mch, pay[%s]', order_id)
            order = recharge_db.get_order(order_id)
            success, order = mch_handler.notify_mch(order)
            if not success:
                # start timer to notify again
                submit_notify_event(order, TIMER_EVENT_TYPE.MCH_NOTIFY)
            _LOGGER.info('notified %s' % event_msg)
        except Exception as e:
            orm.session.rollback()
            _LOGGER.exception('MchNotifyHandler process error.(%s)' % e)
        finally:
            orm.session.close()
        return True


class MchNotifyWithdrawHandler(EventHandler):

    def process(self, event_msg):
        _LOGGER.info('mch notify withdraw Event [%s]' % event_msg)
        order_id = event_msg['order_id']
        try:
            # notify
            _LOGGER.info('to process notify_mch_withdraw, pay[%s]', order_id)
            order = withdraw_db.get_order(order_id)
            success, order = mch_handler.notify_mch_withdraw(order)
            if not success:
                # start timer to notify again
                submit_notify_event(order, TIMER_EVENT_TYPE.MCH_WITHDRAW_NOTIFY)
            _LOGGER.info('notified %s' % event_msg)
        except Exception as e:
            orm.session.rollback()
            _LOGGER.exception('MchNotifyWithdrawHandler process error.(%s)' % e)
        finally:
            orm.session.close()
        return True
